/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including but not limited to the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to provide persons with access to the Software
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGE OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import { AreaLocation, WindowStatusType, AreaAndMargin } from '../common/windowCommon';

const TAG = 'AreaUtils:';

interface MarginType {
  leftTopMargin: number,
  rightTopMargin: number,
  leftBottomMargin: number,
  rightBottomMargin: number,
  leftCenterMargin: number,
  rightCenterMargin: number,
}

interface MarginData {
  left: number,
  right: number,
}

interface ScreenSize {
  width: number,
  height: number,
}

export class AreaUtils {
  private static instance: AreaUtils;
  AVOID_LOCATION = 11;
  AVOID_MARGIN = 0;
  TOP_MARGIN = 0;
  BOTTOM_MARGIN = 0;

  static getInstance(): AreaUtils {
    if (!AreaUtils.instance) {
      AreaUtils.instance = new AreaUtils();
    }
    return AreaUtils.instance;
  }

  setAvoidValue(location: AreaLocation, margin: number): void {
    this.AVOID_LOCATION = location;
    this.AVOID_MARGIN = margin;
  }

  getAvoidValue(): AreaAndMargin {
    return { areaLocation: this.AVOID_LOCATION, marginValue: this.AVOID_MARGIN };
  }

  setTopMargin(margin: number): void {
    this.TOP_MARGIN = margin;
  }

  getTopMargin(): number {
    return this.TOP_MARGIN;
  }

  setBottomMargin(margin: number): void {
    this.BOTTOM_MARGIN = margin;
  }

  getBottomMargin(): number {
    return this.BOTTOM_MARGIN;
  }

  static cameraIsHere(avoidAreaRect: any): boolean {
    return avoidAreaRect.left !== 0 && avoidAreaRect.top !== 0 && avoidAreaRect.width !== 0 && avoidAreaRect.height !== 0;
  }

  private _getTopAvoidAreaLocation(avoidArea: any, location: AreaLocation): AreaAndMargin {
    const left = AreaUtils.px2vp(avoidArea.topRect.left);
    const right = AreaUtils.px2vp(avoidArea.topRect.left + avoidArea.topRect.width);
    const center = window.screen.width / 2;
    let marginValue = left;
    if (left <= center && center <= right) {
      location = AreaLocation.topCenter;
    } else if (center < left) {
      location = AreaLocation.rightTop;
      marginValue = window.screen.width - AreaUtils.px2vp(avoidArea.topRect.left);
    } else {
      location = AreaLocation.leftTop;
    }
    return { areaLocation: location, marginValue: marginValue };
  }

  private _getBottomAvoidAreaLocation(avoidArea: any, location: AreaLocation): AreaAndMargin {
    const left = AreaUtils.px2vp(avoidArea.bottomRect.left);
    const right = AreaUtils.px2vp(avoidArea.bottomRect.left + avoidArea.bottomRect.width);
    const center = window.screen.width / 2;
    let marginValue = AreaUtils.px2vp(avoidArea.bottomRect.left + avoidArea.bottomRect.width);
    if (left <= center && center <= right) {
      location = AreaLocation.bottomCenter;
    } else if (center < left) {
      location = AreaLocation.rightBottom;
      marginValue = right;
    } else {
      location = AreaLocation.leftBottom;
    }
    return { areaLocation: location, marginValue: marginValue };
  }

  private _getLeftAvoidAreaLocation(avoidArea: any, location: AreaLocation): AreaAndMargin {
    const top = AreaUtils.px2vp(avoidArea.leftRect.top);
    const bottom = AreaUtils.px2vp(avoidArea.leftRect.top + avoidArea.leftRect.height);
    const marginValue = AreaUtils.px2vp(avoidArea.leftRect.left + avoidArea.leftRect.width);
    const center = window.screen.height / 2;
    if (top <= center && center <= bottom) {
      location = AreaLocation.leftCenter;
    } else if (center < top) {
      location = AreaLocation.leftBottom;
    } else {
      location = AreaLocation.leftTop;
    }
    return { areaLocation: location, marginValue: marginValue };
  }

  private _getRightAvoidAreaLocation(avoidArea: any, location: AreaLocation): AreaAndMargin {
    const top = AreaUtils.px2vp(avoidArea.rightRect.top);
    const bottom = AreaUtils.px2vp(avoidArea.rightRect.top + avoidArea.rightRect.height);
    const right = window.screen.width - AreaUtils.px2vp(avoidArea.rightRect.left);
    const center = window.screen.height / 2;
    const marginValue = right;
    if (top <= center && center <= bottom) {
      location = AreaLocation.rightCenter;
    } else if (center < top) {
      location = AreaLocation.rightBottom;
    } else {
      location = AreaLocation.rightTop;
    }
    return { areaLocation: location, marginValue: marginValue };
  }

  //获取摄像头避让
  static async getAvoidAreaLocation(): Promise<AreaAndMargin> {
    const location = AreaLocation.none;
    if ((window as any).webClass) {
      const avoidArea = await (window as any).webClass.getAvoidArea();
      console.debug(TAG, `GET Avoid Area Succeed,avoidArea:${JSON.stringify(avoidArea)}`);

      //如果是在顶部，根据屏幕宽度和topRect.left和width判断是在顶部的左中右哪个位置，然后返回AreaLocation和距离
      if (this.cameraIsHere(avoidArea.topRect)) {
        return AreaUtils.getInstance()._getTopAvoidAreaLocation(avoidArea, location);
      }
      //底部情况
      if (this.cameraIsHere(avoidArea.bottomRect)) {
        return AreaUtils.getInstance()._getBottomAvoidAreaLocation(avoidArea, location);
      }
      //左边情况
      if (this.cameraIsHere(avoidArea.leftRect)) {
        return AreaUtils.getInstance()._getLeftAvoidAreaLocation(avoidArea, location);
      }
      //右边情况
      if (this.cameraIsHere(avoidArea.rightRect)) {
        return AreaUtils.getInstance()._getRightAvoidAreaLocation(avoidArea, location);
      }
      return { areaLocation: location, marginValue: 0 };
    }
    return { areaLocation: location, marginValue: 0 };
  }

  //获取屏幕宽高
  static getScreenSize(): ScreenSize {
    const width = AreaUtils.px2vp(window.screen.width);
    const height = AreaUtils.px2vp(window.screen.height);
    console.debug(TAG, `GET Screen Size Succeed,size:${width},${height}`);
    return { width, height };
  }

  //像素转换
  static px2vp(num: number): number {
    if (num) {
      if ((window as any).webClass) {
        return (window as any).webClass.pxToVp(num);
      } else {
        return num;
      }
    } else {
      return 0;
    }
  }

  //处理margin，如果leftTop、leftCenter、leftBottom则为左margin
  static handleMargin(areaAndMargin: AreaAndMargin): MarginData {
    const areaLocation = areaAndMargin.areaLocation;
    const marginValue = areaAndMargin.marginValue;
    //如果leftTop、leftCenter、leftBottom则为左margin
    if (areaLocation === AreaLocation.leftTop || areaLocation === AreaLocation.leftCenter || areaLocation === AreaLocation.leftBottom) {
      return { left: marginValue, right: 0 };
    }
    //如果topCenter、bottomCenter则为居中情况
    if (areaLocation === AreaLocation.topCenter || areaLocation === AreaLocation.bottomCenter) {
      return { left: 0, right: 0 };
    }
    //如果rightTop、rightCenter、rightBottom则为右margin
    if (areaLocation === AreaLocation.rightTop || areaLocation === AreaLocation.rightCenter || areaLocation === AreaLocation.rightBottom) {
      return { left: 0, right: marginValue };
    }
    //其他情况
    return { left: 0, right: 0 };
  }

  //处理handleMargin，根据组件位置判断，组件可以分为顶部、中部、底部，如组件在'top'以及leftTop、rightTop、topCenter则handleMargin()，不然0
  static handleMarginByComponent(componentLocation: AreaLocation, areaAndMargin: AreaAndMargin): MarginData {
    if (componentLocation === areaAndMargin.areaLocation) {
      console.debug(TAG, `handleMargin : ${JSON.stringify(this.handleMargin(areaAndMargin))}`);
      return this.handleMargin(areaAndMargin);
    } else {
      return { left: 0, right: 0 };
    }
  }

  static getMargin(componentLocation: AreaLocation): MarginData {
    return AreaUtils.handleMarginByComponent(componentLocation, AreaUtils.getInstance().getAvoidValue());
  }

  static getAllMargin(): MarginType {
    return {
      leftTopMargin: AreaUtils.getMargin(AreaLocation.leftTop).left,
      rightTopMargin: AreaUtils.getMargin(AreaLocation.rightTop).right,
      leftBottomMargin: AreaUtils.getMargin(AreaLocation.leftBottom).left,
      rightBottomMargin: AreaUtils.getMargin(AreaLocation.rightBottom).right,
      leftCenterMargin: AreaUtils.getMargin(AreaLocation.leftCenter).left,
      rightCenterMargin: AreaUtils.getMargin(AreaLocation.rightCenter).right,
    };
  }

  static checkIfNeedChangeView(): boolean {
    if ((window as any).webClass) {
      if ((window as any).webClass.isFoldAndTablet()) {
        return false;
      } else {
        const orientation = (window.screen.orientation || {}).type;
        const windowStatusType = (window as any).webClass.getWindowStatusType();
        return (orientation === 'landscape-primary' || orientation === 'landscape-secondary') && windowStatusType !== WindowStatusType.SPLIT_SCREEN;
      }
    }
    return false;
  }
}